﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Combined;
using System.Web.Mvc;
using System.Web.Security;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using Microsoft.Ajax.Utilities;
using www.dotnetwise.com.desktop.v1_0;
using Xml.Schema.Linq;

namespace System.Web.Mvc.Controllers
{
	/// <summary>The HomeController class</summary>
	/// <created author="laurentiu.macovei" date="Tue, 08 Jun 2010 22:36:39 GMT"/>
	[HandleError]
	public abstract class APIController
		: Controller
	{

		#region Fields


		#region Const

		private static readonly char[] Semicolon = { ';' };
		private static readonly string BeginWrapper = null;//= "(function (document, window, location, jQuery) {";
		private static readonly string EndWrapper = null;//= "})(document, window, location, window.jQuery);";
		private static readonly string CoreScripts =
			@"
(function() {
window.Debug = window.Debug || function(o) { return o; };
window.NS = window.NS || function() {
	var args = arguments, i=0, j, v, ns = window;
	for(; i<args.length; i++){
		v=args[i];
		ns = window;
		v = v.split('.');
		for(j = 0;j<v.length;j++)
			ns = (ns[v[j]] = ns[v[j]] || {});
    }
	return ns;
};
RegExp.escape = function(text) {
    return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, ""\\$&"");
}
String.toCharCode = function (word) {
  var bytes = [], length = (word || '').length;
  for (var i = 0; i < length; i++) {
   bytes.push(word.charCodeAt(i));
  }
  return bytes;
 }
  var LoadScript = window.LoadScript;
  var lang = LoadScript && LoadScript.lang || 'en';
  LoadScript = window.LoadScript = (function () {
  var loaded = [], computed, undefined;
  var f = function (scriptUrl, power, preventCss) {
   if (typeof scriptUrl === 'number' && isFinite(scriptUrl)) {
    power = scriptUrl;
    scriptUrl = null;
   }
	var head = document.getElementsByTagName ('head')[0] || document.documentElement, name;
	if (typeof power !== 'number'){
		name = (LoadScript.lang && LoadScript.lang+""/"")+"";[""+LoadScript.loaded()+"";""+scriptUrl;
		if (!preventCss){
			var link = document.createElement('link');
			link.type = 'text/css'; link.rel='stylesheet'; link.async = true;
			link.href = """ + (LibConfig.EnableStaticDomains && LibConfig.StaticDomainsHttp.Any() ? LibConfig.StaticDomainsHttp[0] : null) + (LibConfig.RootCss ?? "/").Replace("\"", "\\\"") + @"""+name+';.css';
			head.insertBefore(link, head.firstChild);
		}
		scriptUrl = '"  + (LibConfig.RootRuntimeScripts ?? "/").Replace("\'", "\\'") + @"'+name+';.js';
		power = 0;
	}
	else {
		var byteIndex = Math.floor(power / 8);
		while (loaded.length <= byteIndex)
			loaded.push(0);
		loaded[byteIndex] = loaded[byteIndex] | (1 << (power % 8));
	}
   if (scriptUrl) {
	scriptUrl = '"+(LibConfig.EnableStaticDomains && LibConfig.StaticDomainsHttp.Any() ? LibConfig.StaticDomainsHttp[0] : null)+@"' + scriptUrl;
    if (LoadScript.lazy)
     LoadScript.loading.push(scriptUrl);
    else {
		//var script = document.createElement('script');
		//script.type = 'text/javascript'; script.async = " + LibConfig.DebugJavascriptMode.BitwiseAnd(MinifierDebugMode.False).ToString().ToLower() + @";
		//script.src = scriptUrl;
		//head.insertBefore(script, head.firstChild);
		document.write(""<script type='text/javascript' src='"" + scriptUrl + ""'></script>"")
	}
   }
  }
  f.loading = [];
  f.lang = lang;
  f.loaded = function () {
   if (computed === undefined) {
    computed = Base32.encode(loaded);
   }
   return computed;
  };
  return f;
 })();

 var Base32 = window['Base32'] = {

  // the valid chars for the encoding
  alphabet: '" + Base32.ValidChars + @"',

  /// <summary>
  /// Converts an array of bytes to a Base32-k string.
  /// </summary>
  encode: function (bytes) {
   var sb = '';         // holds the base32 chars
   var index;
   var hi = 5;
   var currentByte = 0;

   while (currentByte < bytes.length) {
    // do we need to use the next byte?
    if (hi > 8) {
     // get the last piece from the current byte, shift it to the right
     // and increment the byte counter
     index = (bytes[currentByte++] >> (hi - 5));
     if (currentByte != bytes.length) {
      // if we are not at the end, get the first piece from
      // the next byte, clear it and shift it to the left
      index = ((((bytes[currentByte] << (16 - hi)) % 256) >> 3) | index);
     }

     hi -= 3;
    } else if (hi == 8) {
     index = (bytes[currentByte++] >> 3);
     hi -= 3;
    } else {

     // simply get the stuff from the current byte
     index = (((bytes[currentByte] << (8 - hi)) % 256) >> 3);
     hi += 5;
    }

    sb += this.alphabet.charAt(index);
   }

   return sb;
  },


  /// <summary>
  /// Converts a Base32-k string into an array of bytes.
  /// </summary>
  /// <exception cref='System.ArgumentException'>
  /// Input string <paramref name='s'>s</paramref> contains invalid Base32-k characters.
  /// </exception>
  decode: function (str) {
   var str_length = str.length
      , numBytes = Math.floor(str_length * 5 / 8), i = numBytes
              , bytes = []
      , ValidChars = this.alphabet;
   while (i--)
    bytes.push(0);

   // all UPPERCASE chars
   //str = str.ToUpper();

   var bit_buffer;
   var currentCharIndex;
   var bits_in_buffer;
   var ValidChars_indexOf = ValidChars.indexOf;

   if (str_length < 3) {
    bytes[0] = ValidChars_indexOf(str[0]) | ValidChars_indexOf(str[1]) << 5;
    return bytes;
   }

   bit_buffer = ValidChars_indexOf(str[0]) | ValidChars_indexOf(str[1]) << 5;
   bits_in_buffer = 10;
   currentCharIndex = 2;
   for (i = 0; i < numBytes; i++) {
    bytes[i] = bit_buffer % 256;
    bit_buffer >>= 8;
    bits_in_buffer -= 8;
    while (bits_in_buffer < 8 && currentCharIndex < str_length) {
     bit_buffer |= ValidChars_indexOf(str[currentCharIndex++]) << bits_in_buffer;
     bits_in_buffer += 5;
    }
   }

   return bytes;
  }
 };
})();
//basics loaded
"
			//@"core\DynamicScripts.js", 
			//@"Core\DynamicScripts\Base64.js",
		;

		#endregion Const

		private MinifierDebugMode DebugJavascript = LibConfig.DebugJavascriptMode;/*System.Web.HttpContext.Current.IsDebuggingEnabled ? DebugJavascript.True : DebugJavascript.False*/
		private MinifierDebugMode DebugCss = LibConfig.DebugCssMode;

		#endregion Fields


		#region Util Methods

		/// <summary>Returns the original redirected url</summary>
		/// <returns></returns>
		/// <created author="laurentiu.macovei" date="Sun, 27 Feb 2011 18:07:40 GMT"/>
		private string GetOriginalUrl()
		{
			var originalUrl = Request.RawUrl;//Request.Url.PathAndQuery
			var combineCssPathLength = Request.FilePath.Length;
			originalUrl = originalUrl.Length < combineCssPathLength ? string.Empty : originalUrl.Substring(combineCssPathLength);
			//find the original URL
			if (originalUrl.StartsWith("?"))
			{
				if (originalUrl.StartsWith("?aspxerrorpath="))
					originalUrl = originalUrl.Substring(15); // ?aspxerrorpath=
				else if (originalUrl.StartsWith("?404;"))
					originalUrl = originalUrl.Substring(1, 5); // ?404;
			}
			else
			{
				if (-1 != originalUrl.IndexOf("errorpath="))
					originalUrl = originalUrl.Substring(14); // aspxerrorpath=
				else if (originalUrl.StartsWith("404;"))
					originalUrl = originalUrl.Substring(4); // ?404;			
			}
			return originalUrl;
		}

		/// <summary>
		/// Processes a script library recursive and only prints unincluded libraries
		/// </summary>
		/// <param name="rootUrl"></param><param name="root"></param><param name="libraryPath"></param><param name="sb"></param>
		/// <param name="loaded"></param><param name="isDependency"></param><param name="loadedWord"></param><param name="loadingPower"></param><returns></returns>
		/// <param name="language">Specifies the language</param>
		/// <created author="laurentiu.macovei" date="Tue, 22 Jun 2010 18:56:58 GMT"/>
		private ContentResult ProcessScriptLibrary(string rootUrl, string root, string libraryPath,
			EnhancedStringBuilder sb, List<string> loaded, bool isDependency, ref byte[] loadedWord,
			ref int loadingPower, string language)
		{
			if (loaded.Contains(libraryPath, StringComparer.OrdinalIgnoreCase))
				return null;
			loaded.Add(libraryPath);
			var path = Path.Combine(root, libraryPath);
			string xmlPath, originalPath = libraryPath;
			if (Directory.Exists(path))
			{
				path = Path.Combine(path, Path.GetFileName(path));
			}
			else
			{
				xmlPath = Path.GetDirectoryName(libraryPath);
				if (!string.IsNullOrEmpty(xmlPath))
					libraryPath = xmlPath;
			}
			xmlPath = path + ".js.xml";
			if (System.IO.File.Exists(xmlPath))// || (System.IO.File.Exists(xmlPath = path + ".xml")))
			{
				var lib = library.Load(xmlPath);
				Response.AddFileDependency(xmlPath);
				if (lib.dependinces != null && lib.dependinces.library != null)
					foreach (var depdenency in lib.dependinces.library)
					{
						var lp = 0;
						var r = ProcessScriptLibrary(rootUrl, root, depdenency.name, sb, loaded, true, ref loadedWord, ref lp, language);
						if (r != null)
							return Content(r.Content + "<br/>The " + (isDependency ? "depdent " : null) + "library " + (rootUrl + libraryPath).Replace('\\', '/') + " could not be loaded because of a missing dependency!");
					}
				if (lib.files != null)
				{
					var lp = 0;
					foreach (var files in lib.files)
						if (files.file != null)
							foreach (var file in files.file)
							{
								var filePath = Path.Combine(libraryPath, Path.Combine(files.path ?? "", file.name ?? "/"));
								var r = ProcessScriptLibrary(rootUrl, root, filePath, sb, loaded, isDependency, ref loadedWord, ref lp, language);
								if (r != null)
									return Content(r.Content + "<br/>The " + (isDependency ? "depdent " : null) + "library " + (rootUrl + libraryPath).Replace('\\', '/') + " could not be loaded  because of a missing file!");
							}
				}
			}
			else if (System.IO.File.Exists(path)
				|| !string.IsNullOrEmpty(path += ".js") && System.IO.File.Exists(path))
			{
				path = Path.GetFullPath(path);
				var power = LibConfig.JavascriptFiles[path.Replace('/', '\\')];
				if (power != loadingPower && !LibConfig.ShouldIncludeLibrary(loadedWord, power))
					return null;
				loadingPower = power;
				LibConfig.AppendLibrary(ref loadedWord, power);
				var locale = Path.Combine(Path.GetDirectoryName(path),
					Path.GetFileNameWithoutExtension(path) + ".en" + Path.GetExtension(path));
				if (System.IO.File.Exists(locale))
					PrintJS(rootUrl, root, sb, locale, power);
				if (language != "en")
				{
					locale = Path.Combine(Path.GetDirectoryName(path),
						Path.GetFileNameWithoutExtension(path) + "." + language + Path.GetExtension(path));
					if (System.IO.File.Exists(locale))
						PrintJS(rootUrl, root, sb, locale, power);
				}
				PrintJS(rootUrl, root, sb, path, power);
			}
			//else if ("Direct/Api".Equals(originalPath, StringComparison.OrdinalIgnoreCase))
			//{
			//    var c = new Ext.Direct.Mvc.DirectController();
			//    c.ControllerContext = new ControllerContext(new System.Web.Routing.RequestContext(HttpContext, new System.Web.Routing.RouteData()), c);
			//    var api = c.Api();
			//    var js = api as JavaScriptResult;
			//    sb.AppendLine(js.Script);
			//    sb.AppendLine("Ext.Direct.addProvider(Ext.app.REMOTING_API);");
			//}
			else
			{
				Response.StatusCode = 404;
				var msg = "The " + (isDependency ? "depdent " : null) + "library " + (rootUrl + originalPath).Replace('\\', '/') + ".xml nor the file " + (rootUrl + originalPath).Replace('\\', '/') + ".js and neither the folder " + (rootUrl + originalPath).Replace('\\', '/') + " exists!";
				return Content(msg);
			}
			return null;
		}

		/// <summary>Prints js recursively</summary>
		/// <param name="rootUrl"></param>
		/// <param name="root"></param>
		/// <param name="sb"></param>
		/// <param name="path"></param>
		/// <param name="power"></param>
		/// <created author="laurentiu.macovei" date="Sun, 27 Feb 2011 18:07:41 GMT"/>
		private void PrintJS(string rootUrl, string root, EnhancedStringBuilder sb, string path, int power)
		{
			//sb.AppendLine("document.writeln(scripts.loaded()+' :: " + Base32.ToBase32String(loadedWord) + "<br/>');");
			Response.AddFileDependency(path);
			if (DebugJavascript.BitwiseAnd(MinifierDebugMode.True))
			{
				sb.Append("LoadScript('")
					.Append(rootUrl.Replace('\\', '/') + 
						path.Substring(root.Length).Replace('\\', '/'))
					.Append("',")
					.Append(power)
					.AppendLine(");");
			}
			else
			{
				sb.Append("LoadScript(").Append(power).Append(");");
				using (var sr = new StreamReader(path))
					sb.AppendLine(sr.ReadToEnd());
			}
		}

		/// <summary>Processes the given css library with all of its dependinces</summary>
		/// <param name="rootLibraries"></param><param name="rootLibrariesPath"></param><param name="libraryPath"></param>
		/// <param name="sb"></param><param name="loaded"></param><param name="isDependency"></param><param name="fileMustExist"></param>
		/// <param name="renderAsImportInDebugMode">Specify true to render as @import url() rather than &lt;link /&gt; tag</param>
		/// <param name="renderPreloadScripts"></param><param name="rootCssPath"></param><returns></returns>
		/// <param name="language">Specifies the language</param>
		/// <created author="laurentiu.macovei" date="Thu, 24 Jun 2010 13:35:49 GMT"/>
		private ContentResult ProcessCssLibrary(string rootLibraries, string rootLibrariesPath,
			string rootCssPath, string libraryPath,
		   EnhancedStringBuilder sb, List<string> loaded, bool isDependency, bool fileMustExist,
		   bool renderAsImportInDebugMode, bool renderPreloadScripts, string language)
		{
			if (loaded.Contains(libraryPath, StringComparer.OrdinalIgnoreCase))
				return null;
			loaded.Add(libraryPath);
			var path = Path.Combine(rootLibrariesPath, libraryPath);
			var cssPath = DebugCss.BitwiseAnd(MinifierDebugMode.False)
				? Path.Combine(rootCssPath, libraryPath)
				: path;
			string xmlPath, originalPath = libraryPath;
			if (Directory.Exists(path))
			{
				var folderName = Path.GetFileName(path);
				path = Path.Combine(path, folderName);
				cssPath = Path.Combine(cssPath, folderName);
			}
			else
			{
				xmlPath = Path.GetDirectoryName(libraryPath);
				if (!string.IsNullOrEmpty(xmlPath))
					libraryPath = xmlPath;
			}
			xmlPath = path + ".js.xml";
			if (System.IO.File.Exists(xmlPath))// || (System.IO.File.Exists(xmlPath = path + ".xml")))
			{
				Response.AddFileDependency(xmlPath);
				var lib = library.Load(xmlPath);
				if (lib.dependinces != null && lib.dependinces.library != null)
					foreach (var depdenency in lib.dependinces.library)
					{
						var r = ProcessCssLibrary(rootLibraries, rootLibrariesPath, rootCssPath, depdenency.name, sb, loaded, true, false, renderAsImportInDebugMode, renderPreloadScripts, language);
						if (r != null)
							return Content(r.Content + "<br/>The " + (isDependency ? "depdent " : null) + "library <b>" + (rootLibraries + libraryPath).Replace('\\', '/') + "</b> could not be loaded because of a missing dependency!");
					}
				if (lib.css != null)
					foreach (var css in lib.css)
					{
						if (css.file != null)
							foreach (var file in css.file)
								if (!(renderPreloadScripts ^ (file.preload.HasValue && file.preload.Value)))
								{
									var libPath = Path.Combine(libraryPath, Path.Combine(css.path ?? "/", file.name ?? "/"));
									var r = ProcessCssLibrary(rootLibraries, rootLibrariesPath, rootCssPath, libPath, sb, loaded, true, true, renderAsImportInDebugMode, renderPreloadScripts, language);
									if (r != null)
										return Content(r.Content + "<br/>\nThe " + (isDependency ? "depdent " : null) + "library <b>" + (rootLibraries + originalPath).Replace('\\', '/') + "</b> could not be loaded  because of a missing file!");
								}
					}
			}
			else if (fileMustExist && System.IO.File.Exists(cssPath))
			{
				var locale = Path.Combine(Path.GetDirectoryName(path),
					Path.GetFileNameWithoutExtension(path) + ".en" + Path.GetExtension(path));
				if (System.IO.File.Exists(locale))
					PrintCss(rootLibraries, rootLibrariesPath, sb, renderAsImportInDebugMode, locale);
				if (language != "en")
				{
					locale = Path.Combine(Path.GetDirectoryName(path),
						Path.GetFileNameWithoutExtension(path) + "." + language + Path.GetExtension(path));
					if (System.IO.File.Exists(locale))
						PrintCss(rootLibraries, rootLibrariesPath, sb, renderAsImportInDebugMode, locale);
				}
				PrintCss(rootLibraries, rootLibrariesPath, sb, renderAsImportInDebugMode, cssPath);
			}
			else if (fileMustExist)
			{
				Response.StatusCode = 404;
				var name = rootLibraries + originalPath;
				name = Path.Combine(Path.GetDirectoryName(name), Path.GetFileNameWithoutExtension(name)).Replace('\\', '/');
				return Content("The " + (isDependency ? "depdent " : null) + "library <b>" + name + ".js.xml</b> nor the file <b>" + name + ".css</b> and neither the folder <b>" + name + "</b> exists!");
			}
			return null;
		}

		private void PrintCss(string rootLibraries, string rootLibrariesPath, EnhancedStringBuilder sb, bool renderAsImportInDebugMode, string cssPath)
		{
			Response.AddFileDependency(cssPath);
			if (DebugCss.BitwiseAnd(MinifierDebugMode.True))
			{
				if (renderAsImportInDebugMode)
					sb.AppendLine("@import url('" + (Url.StaticContent(rootLibraries + cssPath.Substring(rootLibrariesPath.Length)).Replace('\\', '/')) + "');");
				else sb.AppendLine("<link rel='stylesheet' src='" + Url.StaticContent((rootLibraries + cssPath.Substring(rootLibrariesPath.Length)).Replace('\\', '/')) + "' type='text/css' />');");
			}
			else
			{
				using (var sr = new StreamReader(cssPath))
					sb.AppendLine(sr.ReadToEnd());
			}
		}


		#endregion Util Methods


		#region Business Methods

		/// <summary>Combines the required javascript files and returns a single minified result including all the dependent libraries</summary>
		/// <returns></returns>
		/// <created author="laurentiu.macovei" date="Tue, 22 Jun 2010 15:31:47 GMT"/>
		[OutputCache(Duration = 999999, VaryByParam = "*", Location = System.Web.UI.OutputCacheLocation.Any)]//, VaryByParam="*")]
		public virtual ActionResult CombineJS(string aspxerrorpath)
		{
			var m = new Minifier();
			var rootLibraries = LibConfig.RootLibraries;
			var rootRuntimeScripts = LibConfig.RootRuntimeScripts;
			var originalUrl = Request.Url.PathAndQuery;
			var iis6url = aspxerrorpath;
			if (iis6url != null)
			{
				iis6url = rootRuntimeScripts + iis6url;
				var path = Server.MapPath(iis6url);
				if (System.IO.File.Exists(path))
					return File(path, "text/javascript");
				originalUrl = ";" + Request.Url.AbsoluteUri.Substring(0, Request.Url.AbsoluteUri.IndexOf(Request.Url.AbsolutePath)) + iis6url + Request.Url.Query;
			}
			var index = (originalUrl ?? string.Empty).IndexOf(';');
			string language = "en";
			if (index >= 0)
				try
				{
					var sb = new EnhancedStringBuilder();
					var url = new Uri(originalUrl.Substring(index + 1));
					var prettify = (url.Query ?? "").IndexOf("format=1", StringComparison.OrdinalIgnoreCase) >= 0;
					if ((url.Query ?? "").IndexOf("debug=0") >= 0)
						DebugJavascript = MinifierDebugMode.ClearFalse;
					if (prettify)
						DebugJavascript = MinifierDebugMode.ClearTrue;
					index = (url.LocalPath ?? string.Empty).IndexOf(rootRuntimeScripts, StringComparison.OrdinalIgnoreCase);
					if (index >= 0)
					{
						var langIndex = url.LocalPath.IndexOf('/', index + rootRuntimeScripts.Length);
						if (langIndex != -1)
						{
							language = url.LocalPath.Substring(index + rootRuntimeScripts.Length, langIndex - index - rootRuntimeScripts.Length);
							langIndex = language.Length + 1;
						}
						else langIndex = 0;

						var scriptPath = url.LocalPath.Substring(index + rootRuntimeScripts.Length + langIndex);
						var scripts = scriptPath.Split(Semicolon, StringSplitOptions.RemoveEmptyEntries);
						byte[] loadedWord = new byte[] { 0 };
						var loaded = new List<string>();
						var scriptsLength = scripts.Length;
						var scriptsSkip = 0;
						sb.Append(BeginWrapper);
						if (scripts.Length > 0 && scripts[0].StartsWith("["))
						{
							if (scripts[0].Length > 1)
								loadedWord = Base32.FromBase32String(scripts[0].Substring(1));
							scriptsLength--;
							scriptsSkip++;
						}
						else
						{
							//CoreScripts.ForEach(urlPath =>
							//{
							//    var path = Path.Combine(LibConfig.RootLibrariesPath, urlPath);
							//    using (var sr = new StreamReader(path))
							//        sb.AppendLine(sr.ReadToEnd());
							//    var power = LibConfig.JavascriptFiles[path];
							//    sb.Append("LoadScript(").Append(power).AppendLine(");");
							//    LibConfig.AppendLibrary(ref loadedWord, power);
							//});
							sb.Append(CoreScripts);
						}
						var rootLibrariesPath = LibConfig.RootLibrariesPath;
						var inScripts = scripts.Skip(scriptsSkip);
						//BeginWrapper.Concat(scripts.Skip(scriptsSkip)).Concat(EndWrapper);
						//if (DebugJavascript.BitwiseAnd(MinifierDebugMode.True))
						//    inScripts = inScripts.Skip(1).Take(scriptsLength);
						var lp = 0;
						foreach (var script in inScripts)
						{
							var r = ProcessScriptLibrary(rootLibraries, rootLibrariesPath, script.EndsWith(".js", StringComparison.OrdinalIgnoreCase) ? Path.Combine(Path.GetDirectoryName(script), Path.GetFileNameWithoutExtension(script)) : script, sb, loaded, false, ref loadedWord, ref lp, language);
							if (r != null)
								return r;
						}
						sb.Append(EndWrapper);
						string minified = null;
						if (DebugJavascript.BitwiseAnd(MinifierDebugMode.False))
						{
							var settings = new CodeSettings
							{
								CollapseToLiteral = true,
								EvalTreatment = EvalTreatment.Ignore,
								InlineSafeStrings = true,
								LocalRenaming = LocalRenaming.CrunchAll,
								MacSafariQuirks = true,
								KillSwitch = DebugJavascript.BitwiseAnd(MinifierDebugMode.False) ? 0 : 0,
								MinifyCode = true,
								OutputMode = prettify ? OutputMode.MultipleLines : OutputMode.SingleLine,
								PreserveFunctionNames = false,
								RemoveFunctionExpressionNames = true,
								RemoveUnneededCode = true,
								DebugLookupList = "Debug",
								StripDebugStatements = (url.Query ?? "").IndexOf("strip=0", StringComparison.OrdinalIgnoreCase) < 0
							};
							try
							{
								minified = m.MinifyJavaScript(sb.ToString(), settings);
							}
							catch (Exception ex)
							{
								minified = "//" + ex.Message + "\n" + minified;
							}
							//fallback on any error
							minified = string.IsNullOrEmpty(minified) ? sb.ToString() : minified;
						}
						else minified = sb.ToString();

						scriptPath = Server.MapPath(url.LocalPath);
						var dir = Path.GetDirectoryName(scriptPath);
						minified = "//" + Base32.ToBase32String(loadedWord) + "\r\n" + minified;
						if (!DebugJavascript.BitwiseAnd(MinifierDebugMode.NotPersist))
						{
							if (!Directory.Exists(dir))
								Directory.CreateDirectory(dir);
							using (var sw = new StreamWriter(scriptPath))
								sw.Write(minified);
						}
						return Content(minified, "text/javascript");
					}
				}
				catch (Exception ex)
				{
					return Content(ex.Message + ex.StackTrace);
				}
			return Content("404 not found");
		}

		/// <summary>
		/// </summary>
		/// <returns></returns>
		/// <created author="laurentiu.macovei" date="Thu, 24 Jun 2010 13:35:49 GMT"/>
		[OutputCache(Duration = 999999, VaryByParam = "*", Location = System.Web.UI.OutputCacheLocation.Any)]//, VaryByParam="*")]
		public ActionResult CombineCSS(string aspxerrorpath)
		{
			var m = new Minifier();
			var rootCss = LibConfig.RootCss;
			var originalUrl = Request.Url.PathAndQuery;
			var iis6url = aspxerrorpath;
			if (iis6url != null)
			{
				iis6url = rootCss + iis6url;
				var path = Server.MapPath(iis6url);
				if (System.IO.File.Exists(path))
					return File(path, "text/css");
				originalUrl = ";" + Request.Url.AbsoluteUri.Substring(0, Request.Url.AbsoluteUri.IndexOf(Request.Url.AbsolutePath)) + iis6url;
			}
			string language = "en";
			var index = (originalUrl ?? string.Empty).IndexOf(';');
			try
			{
				if (index >= 0)
				{
					var sb = new EnhancedStringBuilder();

					var url = new Uri(originalUrl.Substring(index + 1));
					if ((url.Query ?? "").IndexOf("debug=0") >= 0)
						DebugCss = MinifierDebugMode.False;
					index = (url.LocalPath ?? string.Empty).IndexOf(rootCss, StringComparison.OrdinalIgnoreCase);
					if (index >= 0)
					{
						var langIndex = url.LocalPath.IndexOf('/', index + rootCss.Length);
						if (langIndex != -1)
						{
							language = url.LocalPath.Substring(index + rootCss.Length, langIndex - index - rootCss.Length);
							langIndex = language.Length + 1;
						}
						else langIndex = 0;

						var scriptPath = url.LocalPath.Substring(index + rootCss.Length + langIndex);
						var scripts = scriptPath.Split(Semicolon, StringSplitOptions.RemoveEmptyEntries);
						var rootLibraries = LibConfig.RootLibraries;
						var rootLibrariesPath = LibConfig.RootLibrariesPath;
						var rootCssPath = LibConfig.RootCssPath;
						var loaded = new List<string>();
						var renderAsImportInDebugMode = true;
						var renderPreloadScripts = scripts.Length > 0 && "preload" == scripts[0];
						foreach (var script in scripts)
						{
							var r = ProcessCssLibrary(rootLibraries, rootLibrariesPath,
								rootCssPath,
								script.EndsWith(".js", StringComparison.OrdinalIgnoreCase)
									? Path.Combine(Path.GetDirectoryName(script), Path.GetFileNameWithoutExtension(script))
									: script,
								sb, loaded, false, false, renderAsImportInDebugMode,
								renderPreloadScripts, language);
							if (r != null)
								return r;
						}
						string minified;
						if (DebugCss.BitwiseAnd(MinifierDebugMode.False))
						{
							var prettify = (url.Query ?? "").IndexOf("format=1", StringComparison.OrdinalIgnoreCase) >= 0;
							minified = m.MinifyStyleSheet(sb.ToString(), new CssSettings
							{
								//ColorNames = CssColor.
								CommentMode = CssComment.None,
								OutputMode = prettify ? OutputMode.MultipleLines : OutputMode.SingleLine,
								//IndentSpaces = 0,
								//Severity = 0,
								TermSemicolons = prettify
							});
						}
						else minified = sb.ToString();

						scriptPath = Server.MapPath(url.LocalPath);
						var dir = Path.GetDirectoryName(scriptPath);
						if (!DebugCss.BitwiseAnd(MinifierDebugMode.NotPersist))
						{
							if (!Directory.Exists(dir))
								Directory.CreateDirectory(dir);
							using (var sw = new StreamWriter(scriptPath))
								sw.Write(minified);
						}
						return Content(minified, "text/css");
					}
				}
			}
			catch (Exception ex)
			{
				return Content(ex.Message + "<br>\n" + ex.StackTrace);
			}
			return Content("404 not found");
		}

		/// <summary>
		/// </summary>
		/// <returns></returns>
		/// <created author="laurentiu.macovei" date="Tue, 08 Jun 2010 22:36:39 GMT"/>
		public ActionResult Index()
		{
			ViewData["Message"] = "Welcome to Tasks Management API!";

			return new ContentResult { Content = "Welcome to Tasks Management API" };// View();
		}

		/// <summary>
		/// </summary>
		/// <returns></returns>
		/// <created author="laurentiu.macovei" date="Mon, 14 Jun 2010 16:15:58 GMT"/>
		public ActionResult Code()
		{
			return new ContentResult
			{
				ContentType = "application/json",
				Content = @"
{
	'metaData': {
		'totalProperty': 'total',
		'root': 'records',
		'id': 'id',
		'fields': [{
			'name': 'id',
			'type': 'int'
		},
		 {
			'name': 'name',
			'type': 'string'
		 }]
	},
	'success': true,
	'total': 50,
	'records': [{
		'id': '1',
		'name': 'AAA'
	}, {
		'id': '2',
		'name': 'BBB'
	}],
	'columns': [{
		'header': '#ID',
		'dataIndex': 'id'
	}, {
		'header': 'User',
		'dataIndex': 'name'
	}]
}"
			};

		}


		#endregion Business Methods
	}
}
